package com.googlecode.chios.jnet.utils;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * 
 * 字符编码
 * 
 * @author luzj
 * 
 */
public class CharsetUtil {

	public static final Charset UTF_8 = Charset.forName("UTF-8");

	public static final Charset GBK = Charset.forName("GBK");

	public static final Charset UTF_16 = Charset.forName("UTF-16");

	public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");

	public static final Charset US_ASCII = Charset.forName("US-ASCII");

	private static final ThreadLocal<Map<Charset, CharsetEncoder>> encoders = new ThreadLocal<Map<Charset, CharsetEncoder>>() {
		@Override
		protected Map<Charset, CharsetEncoder> initialValue() {
			return new IdentityHashMap<Charset, CharsetEncoder>();
		}
	};

	private static final ThreadLocal<Map<Charset, CharsetDecoder>> decoders = new ThreadLocal<Map<Charset, CharsetDecoder>>() {
		@Override
		protected Map<Charset, CharsetDecoder> initialValue() {
			return new IdentityHashMap<Charset, CharsetDecoder>();
		}
	};

	/**
	 * Returns a cached thread-local {@link CharsetEncoder} for the specified
	 * <tt>charset</tt>.
	 */
	public static CharsetEncoder getEncoder(Charset charset) {
		if (charset == null) {
			throw new NullPointerException("charset");
		}

		Map<Charset, CharsetEncoder> map = encoders.get();
		CharsetEncoder e = map.get(charset);
		if (e != null) {
			e.reset();
			e.onMalformedInput(CodingErrorAction.REPLACE);
			e.onUnmappableCharacter(CodingErrorAction.REPLACE);
			return e;
		}

		e = charset.newEncoder();
		e.onMalformedInput(CodingErrorAction.REPLACE);
		e.onUnmappableCharacter(CodingErrorAction.REPLACE);
		map.put(charset, e);
		return e;
	}

	/**
	 * Returns a cached thread-local {@link CharsetDecoder} for the specified
	 * <tt>charset</tt>.
	 */
	public static CharsetDecoder getDecoder(Charset charset) {
		if (charset == null) {
			throw new NullPointerException("charset");
		}

		Map<Charset, CharsetDecoder> map = decoders.get();
		CharsetDecoder d = map.get(charset);
		if (d != null) {
			d.reset();
			d.onMalformedInput(CodingErrorAction.REPLACE);
			d.onUnmappableCharacter(CodingErrorAction.REPLACE);
			return d;
		}

		d = charset.newDecoder();
		d.onMalformedInput(CodingErrorAction.REPLACE);
		d.onUnmappableCharacter(CodingErrorAction.REPLACE);
		map.put(charset, d);
		return d;
	}

}
